from google.appengine.ext import db
import simplejson as json
from django.http import HttpResponse
import logging


class Dummy(object):
    pass

globalEntities = Dummy()


class GaeQueryModels(db.Expando):
    # key_name is the model name
    entityCount = db.IntegerProperty(required=True, indexed=False, default=0)

def getGaeQueryModel(entityName):
    entityMetadata = GaeQueryModels.get_by_key_name(entityName)
    if entityName is None:
        return GaeQueryModels(key_name=entityName)
    
def createExpandoEntityInCurrentContext(entityName):
    proceed = True
    # logging.debug(str(globals()))
    if not hasattr(globalEntities, entityName):
        # Create it.
        crStr = \
"""class %s(db.Expando):
    pass
globalEntities.%s = %s
""" % (entityName, entityName, entityName)
        exec(crStr)
        # globals[entityName] = locals[entityName]
    elif isinstance(getattr(globalEntities, entityName), type(db.Expando)):
        # Cool, we are good to go.
        pass
    else:
        # Aiee!! Oops, we are probably going to clobber something.
        proceed = False
    return proceed

def getNewExpandoEntity(entityName, key = None, key_name=None, attributes=[]):
    if not createExpandoEntityInCurrentContext(entityName):
        return None
    if key is not None:
        getStr = "globalEntities.%s.get" % entityName
        obj = eval(getStr)(key)
    elif key_name is not None:
        getStr = "globalEntities.%s" % entityName
        obj = eval(getStr)(key_name=key_name)
    else:
        getStr = "globalEntities.%s()" % entityName
        obj = eval(getStr)
    for attr in attributes:
        setattr(obj, attr, attributes[attr])
    if obj._entity:
        keys = obj._entity.keys()
        for key in keys:
            if key not in attributes:
                del obj._entity[key]
        
    return obj


def get_multi(request):
    model = request.GET['model']
    filters = json.loads(request.GET['filters'])
    order = request.GET['order']
    limit = int(request.GET['limit'])
    offset = int(request.GET['offset'])
    
    createExpandoEntityInCurrentContext(model)
    q = db.Query(getattr(globalEntities, model))
    for f in filters:
        q.filter(f[0], f[1])
    if len(order.strip()) > 0:
        q.order(order)
    resultSet = q.fetch(limit, offset)
    response = HttpResponse()
    response.write(serializeResultSet(resultSet))
    return response
    

def put_single(request):
    attrs = json.loads(request.POST['object'])
    model = request.POST['model']

    key_name = None
    key_string = None
    if "__key" in attrs:
        key = attrs["__key"]
        if "__name" in key and key['__name'] is not None:
            key_name = key['__name']
        if "__repr" in key and key['__repr'] is not None:
            key_string = key['__repr']
        del attrs["__key"]
    obj = getNewExpandoEntity(entityName=model, 
                              key_name=key_name, 
                              key=key_string, 
                              attributes=attrs)
    obj.put()
    response = HttpResponse()
    response.write(json.dumps( 
        { "__key": 
          { "__name": obj.key().name(),
            "__kind": obj.key().kind(), 
            "__repr": str(obj.key()),
          }, 
          "__is_saved": obj.is_saved(),
        }))
    return response
 
def delete_single(request):
    key = json.loads(request.POST['object'])
    model = request.POST['model']

    key_string = None
    if "__repr" in key and key['__repr'] is not None:
        key_string = key['__repr']
    obj = getNewExpandoEntity(entityName=model, 
                              key=key_string)
    if obj.is_saved():
        obj.delete()
    response = HttpResponse()
    response.write(json.dumps( 
        { "__key": 
          { "__name": None,
            "__kind": model, 
            "__repr": None,
          }, 
          "__is_saved": False,
        }))
    return response


def stripObject(obj):
    tmp = { }
    for key in obj._entity:
        tmp[key] = obj._entity[key]
    tmp["__key"] = { "__name": obj.key().name(), 
                     "__kind": obj.key().kind(), 
                     "__repr": str(obj.key()), 
                   }
    tmp["__is_saved"] = obj.is_saved()
    return tmp

def serializeResultSet(resultSet):
    return json.dumps(map(lambda x: stripObject(x), resultSet))
